﻿using CPPEI.Coolzon.UI.Data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace CPPEI.Coolzon.UI
{
    /// <summary>
    /// 场景更新事件
    /// </summary>
    /// <param name="scene"></param>
    public delegate void SceneUpdated(ScenePart scene);

    /// <summary>
    /// 场景打开事件
    /// </summary>
    /// <param name="scene"></param>
    public delegate void SceneOpened(ScenePart scene);

    /// <summary>
    /// 缩放
    /// </summary>
    /// <param name="oldFactor"></param>
    /// <param name="newFactor"></param>
    public delegate void ZoomEventHandler(double oldFactor, double newFactor);

    /// <summary>
    /// 组件框架可以承载组件
    /// 每一个PartFrame具有一个PartContext
    /// </summary>
    public partial class PartFrame : Part, ILayoutContainer
    {
        static PartFrame()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(PartFrame), new FrameworkPropertyMetadata(typeof(PartFrame)));
        }

        /// <summary>
        /// 组件运行的上下文
        /// </summary>
        public PartContext PartContext { get; private set; }

        public double HorizontalOffset
        {
            get
            {
                return (double)this.GetValue(HorizontalOffsetProperty);
            }
            set
            {
                this.SetValue(HorizontalOffsetProperty, value);
            }
        }

        public double VerticalOffset
        {
            get
            {
                return (double)this.GetValue(VerticalOffsetProperty);
            }
            set
            {
                this.SetValue(VerticalOffsetProperty, value);
            }
        }
        #region dependency properties

        public static readonly DependencyProperty HorizontalOffsetProperty =
            DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(PartFrame),
            new PropertyMetadata(Double.MinValue, new PropertyChangedCallback(PartFrame.OnHorizontalOffsetPropertyChanged)));

        public static readonly DependencyProperty VerticalOffsetProperty =
            DependencyProperty.Register("VerticalOffset", typeof(double), typeof(PartFrame),
            new PropertyMetadata(Double.MinValue, new PropertyChangedCallback(PartFrame.OnVerticalOffsetPropertyChanged)));

        #endregion

        #region scroll
        public Size FrameSize { get; private set; }
        public Size ContentSize { get; private set; }
        /// <summary>
        /// 是否已经更新过显示模式了，只有更新过显示模式之后，大小变动事件才会激活重新更新显示模式
        /// </summary>
        private bool _hasUpdateDisplayMode = false;
        #endregion

        /// <summary>
        /// 需要滚动的水平偏移值，对于场景的循环显示
        /// </summary>
        private double _hLoopOffset;

        public Layout Layout { get; set; }

        public PartFrameDisplayMode DisplayMode { get; set; }

        private Grid _container;
        /// <summary>
        /// 当前显示的组件
        /// </summary>
        private Part _currentPart;
        /// <summary>
        /// 上一个场景
        /// </summary>
        private Part _lastPart;
        /// <summary>
        /// 本次要显示的场景
        /// </summary>
        private Part _enteringPart;
        /// <summary>
        /// 进入的场景的动画
        /// </summary>
        private SwitchAnimation _enteringAnimation;

        private Part _leaveingPart;
        private Storyboard _switchStoryboard;

        #region animation

        ScaleTransform _scaleIn;
        ScaleTransform _scaleOut;
        DoubleAnimation _aniInOpacity;
        DoubleAnimation _animationIn;
        DoubleAnimation _animationInY;
        DoubleAnimation _aniOutOpacity;
        DoubleAnimation _animationOut;
        #endregion

        ///// <summary>
        ///// 记录区域实际的偏移值，用于定位到区域
        ///// </summary>
        //Dictionary<Part, Point> _areaActualOffset;

        Canvas _scrollViewer;

        private bool _isCanScroll = false;
        /// <summary>
        /// 是否可以滚动
        /// </summary>
        [Obsolete()]
        public bool IsCanScroll
        {
            get
            {
                return _isCanScroll;
            }
            set
            {
                if (_isCanScroll != value)
                {
                    if (value)
                    {
                        this.Content = _scrollViewer;
                        //this._scrollViewer.Content = _container;
                        this._scrollViewer.Children.Add(_container);
                    }
                    else
                    {
                        //this._scrollViewer.Content = null;
                        this._scrollViewer.Children.Clear();
                        this.Content = _container;
                    }
                }
                _isCanScroll = value;
            }
        }

        private bool _isAutoSize = false;

        /// <summary>
        /// 移动区域时的动画
        /// </summary>
        private Storyboard _moveAreaStoryboard;
        private string _moveSourceArea;
        private string _moveDestArea;

        [Obsolete("请使用CurrentScene来获取当前场景")]
        public Part CurrentPart
        {
            get
            {
                return _currentPart;
            }
        }

        /// <summary>
        /// 切换动画
        /// </summary>
        private SwitchAnimation _switchAnimation;
        private SwitchType _switchType;

        private Storyboard _scrollStoryBoard;

        public event SceneUpdated OnSceneUpdated;

        /// <summary>
        /// 场景打开事件
        /// </summary>
        public event SceneOpened OnSceneOpened;

        /// <summary>
        /// 移动激光笔的动画
        /// </summary>
        private Storyboard _moveLaserPointerStoryboard;
        private DoubleAnimation _moveLaserPointerAnimationLeft;
        private DoubleAnimation _moveLaserPointerAnimationTop;

        /// <summary>
        /// 移动放大镜的动画
        /// </summary>
        private Storyboard _moveMagnifyStoryboard;
        private DoubleAnimation _moveMagnifyAnimationLeft;
        private DoubleAnimation _moveMagnifyAnimationTop;

        /// <summary>
        /// 放大倍数
        /// </summary>
        private double _magnifyRate = 1.5d;

        /// <summary>
        /// 缩放事件
        /// </summary>
        public event ZoomEventHandler Zoom;

        public PartFrame()
        {
            IsCanScroll = false;
            DisplayMode = PartFrameDisplayMode.Original;
            _container = new Grid();
            //_container.Background = new SolidColorBrush(Colors.White);

            _scrollViewer = new Canvas();
            //_scrollViewer.Background = new SolidColorBrush(Colors.White);
            //_scrollViewer.Padding = new Thickness(0);
            //_scrollViewer.Margin = new Thickness(0);
            //_scrollViewer.BorderThickness = new Thickness(0);
            //_scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
            //_scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;

            //_scrollViewer.PanningMode = PanningMode.Both;
            //_scrollViewer.PanningMode = PanningMode.Both;
            //_scrollViewer.CanContentScroll = true;
            //_scrollViewer.ScrollChanged += _scrollViewer_ScrollChanged;

            //_scrollViewer.Content = _container;
            this.Content = _container;

            //this.Background = new SolidColorBrush(Colors.Green);
            //this._container.Background = new SolidColorBrush(Colors.Yellow);

            this.ZoomFactor = 1.0d;

            TransformGroup tfGroup = new TransformGroup();
            this._scrollViewer.RenderTransform = tfGroup;
            _scaleTransform = new ScaleTransform();
            _scaleTransform.CenterX = 0.5f;
            _scaleTransform.CenterY = 0.5f;
            tfGroup.Children.Add(_scaleTransform);
        }

        void _scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            ValidateCurrentPartVisibleRange();

            if (_currentPart != null)
            {
                if (OnSceneUpdated != null)
                {
                    OnSceneUpdated(_currentPart as ScenePart);
                }
            }
        }

        /// <summary>
        /// 校验实际的显示区域，用于帮助activex组件裁剪
        /// </summary>
        public void ValidateCurrentPartVisibleRange()
        {
            if (_currentPart != null)
            {
                Point ltInContainer = _scrollViewer.PointToScreen(new Point(0, 0));
                Point rtInContainer = _scrollViewer.PointToScreen(new Point(_scrollViewer.ActualWidth, _scrollViewer.ActualHeight));
                _currentPart.VisibleRegionChange(ltInContainer, rtInContainer);
            }
        }

        /// <summary>
        /// frame的大小和显示的组件的大小一样大
        /// </summary>
        public void SetAutoSize()
        {
            _isAutoSize = true;
            if (this._currentPart != null)
            {
                this.Width = this._currentPart.XWidth;
                this.Height = this._currentPart.XHeight;
            }
        }

        /// <summary>
        /// 加在组件，但是并不显示组件
        /// </summary>
        /// <param name="part"></param>
        /// <param name="isShowActiveXPart">是否显示ActiveX组件</param>
        public void PreliminaryLoadPart(ScenePart scenePart, bool isShowActiveXPart)
        {
            if (!this._container.Children.Contains(scenePart))
            {
                this._container.Children.Add(scenePart);
            }
            SetPartVisible(scenePart, false);

            PartContext context = CreatePartContext(scenePart.SceneMatadata);
            context.IsShowActiveXPart = isShowActiveXPart;

            context.IsPreviewLoadData = false;
            context.SceneMetadata = scenePart.SceneMatadata;
            scenePart.Init(context);
        }

        /// <summary>
        /// 隐藏组件，只是让组件无法显示在可视区域里而已
        /// </summary>
        /// <param name="part"></param>
        /// <param name="isVisible"></param>
        private void SetPartVisible(Part part, bool isVisible)
        {
            if (isVisible)
            {
                if (!_container.Children.Contains(part))
                {
                    _container.Children.Add(part);
                }
                //part.Visibility = System.Windows.Visibility.Visible;
                //part.Margin = new Thickness(0, 0, 0, 0);
            }
            else
            {
                if (_container.Children.Contains(part))
                {
                    _container.Children.Remove(part);
                }
                //part.Visibility = System.Windows.Visibility.Hidden;
                //part.Margin = new Thickness(-99999, -99999, 99999, 99999);
            }
        }

        /// <summary>
        /// 显示组件,但是需要Active之后才能真正的替换
        /// </summary>
        /// <param name="part"></param>
        /// <param name="switchAnimation"></param>
        public void ShowPart(Part part, SwitchAnimation switchAnimation)
        {
            this._enteringPart = part;
            this._leaveingPart = this._currentPart;

            //// 销毁退出的场景
            //if (this._leaveingPart != null)
            //{
            //    Common.Logger.DebugToTag("UI", "销毁-位置4,leaveingPart，Name:{0}", _leaveingPart.Name);
            //    this.SetPartVisible(_leaveingPart, false);
            //    // 销毁当前场景
            //    this._leaveingPart.Destory();
            //    this._leaveingPart = null;
            //}

            //_leaveingPart = _currentPart;
            //// 把当前组件设置为要显示的组件
            //_currentPart = part;
            //_enteringPart = part;
            //_enteringAnimation = switchAnimation;
            //_enteringAnimation.Prepare(SwitchType.In, this, part);
            /*
            if (_currentPart != null)
            {
                // 销毁现有的场景
                this.CurrentScene.Destory();
            }
            this._currentPart = part;*/

            // 关闭放大镜和激光笔
            this.HideMagnify();
            this.HideLaserPointer();
        }

        /// <summary>
        /// 删除框架里的组件
        /// </summary>
        /// <returns></returns>
        public UI.Part RemoveCurrentPart()
        {
            if (_currentPart != null)
            {
                this._container.Children.Remove(_currentPart);
            }
            UI.Part part = _currentPart;
            _currentPart = null;
            return part;
        }

        /// <summary>
        /// 滚动到子组件位置,当场景很大的时候无法直接显示，可以调用此方法滚动到指定的区域
        /// </summary>
        /// <param name="part"></param>
        public void ScrollToPart(AreaPart part)
        {
            if (this.Content != this._scrollViewer)
            {
                return;
            }

            if (_scrollStoryBoard != null)
            {
                _scrollStoryBoard.Stop();
                _scrollStoryBoard = null;
            }
            //Point ptPart = this._areaActualOffset[part];
            //part.PointToScreen(new Point(0, 0));
            //Point ptScrollView = this._scrollViewer.PointToScreen(new Point(0, 0));
            double deltaX = part.XLeft;// this._scrollViewer.HorizontalOffset + ptPart.X - ptScrollView.X;
                                       //double deltaY = this._scrollViewer.VerticalOffset + ptPart.Y - ptScrollView.Y;

            _scrollStoryBoard = new Storyboard();
            _scrollStoryBoard.FillBehavior = FillBehavior.HoldEnd;
            ////DoubleAnimation hScrollAnimation = new DoubleAnimation(this._scrollViewer.HorizontalOffset, deltaX, new Duration(TimeSpan.FromMilliseconds(500)));
            ////Storyboard.SetTarget(hScrollAnimation, this);
            ////Storyboard.SetTargetProperty(hScrollAnimation, new PropertyPath(PartFrame.HorizontalOffsetProperty));


            //DoubleAnimation vScrollAnimation = new DoubleAnimation(this._scrollViewer.VerticalOffset, deltaY, new Duration(TimeSpan.FromMilliseconds(500)));
            //Storyboard.SetTarget(vScrollAnimation, this);
            //Storyboard.SetTargetProperty(vScrollAnimation, new PropertyPath(PartFrame.VerticalOffsetProperty));

            ////_scrollStoryBoard.Children.Add(hScrollAnimation);
            //storyBoard.Children.Add(vScrollAnimation);
            _scrollStoryBoard.Begin();

            //this._scrollViewer.ScrollToHorizontalOffset(deltaX);
            //this._scrollViewer.ScrollToVerticalOffset(deltaY);
        }

        /// <summary>
        /// 滚动到一个具体的位置
        /// </summary>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        public void MoveCameraToPos(double offsetX, double offsetY)
        {
            if (_currentPart != null)
            {
                double cameraWidth = this.ActualWidth;
                double cameraHeight = this.ActualHeight;
                double sceneWidth = this._currentPart.XWidth;
                double sceneHeight = this._currentPart.XHeight;


                if (offsetX <= 0)
                {
                    offsetX = 0;
                }
                else if (cameraWidth > sceneWidth)
                {
                    Debug.WriteLine(string.Format("PartFrame MoveCameraToPos cameraWidth > sceneWidth OffsetX:{0} OffsetY:{1}", offsetX, offsetY));
                    offsetX = 0;
                }
                else if (offsetX + cameraWidth > sceneWidth)
                {
                    offsetX = sceneWidth - cameraWidth;
                }

                if (offsetY <= 0)
                {
                    offsetY = 0;
                }
                else if (cameraHeight > sceneHeight)
                {
                    Debug.WriteLine(string.Format("PartFrame MoveCameraToPos cameraHeight > sceneHeight OffsetX:{0} OffsetY:{1}", offsetX, offsetY));
                    offsetY = 0;
                }
                else if (offsetY + cameraHeight > sceneHeight)
                {
                    offsetY = sceneHeight - cameraHeight;
                }

                bool hasChanged = false;

                if (this.HorizontalOffset != offsetX)
                {
                    hasChanged = true;
                    this.HorizontalOffset = offsetX;
                }

                if (this.VerticalOffset != offsetY)
                {
                    hasChanged = true;
                    this.VerticalOffset = offsetY;
                }

                if (hasChanged)
                {
                    _scrollViewer_ScrollChanged(null, null);
                }
            }
        }

        /// <summary>
        /// 获取摄像机的位置（左上角)
        /// </summary>
        /// <returns></returns>
        public Point GetCameraPos()
        {
            return new Point(this.HorizontalOffset, this.VerticalOffset);
        }

        ///// <summary>
        ///// 保存场景中区域的相对位置
        ///// </summary>
        //public void StoreAreaActualOffset()
        //{
        //    // 保存区域的相对位置
        //    if (_areaActualOffset == null)
        //    {
        //        ScenePart scenePart = (_currentPart as ScenePart);
        //        _areaActualOffset = new Dictionary<Part, Point>();
        //        for (int index = 0; index < scenePart.SceneMatadata.Areas.Count; index++)
        //        {
        //            Coolzon.Metadata.Area areaMetadata = scenePart.SceneMatadata.Areas[index];
        //            UI.AreaPart areaPart = scenePart.GetChildPart(areaMetadata.Name, false) as UI.AreaPart;
        //            _areaActualOffset.Add(areaPart, areaPart.PointToScreen(new Point(0, 0)));
        //        }
        //    }
        //}

        ///// <summary>
        ///// 评级切换动画
        ///// </summary>
        ///// <param name="part"></param>
        //public void ShowPartWithAnimationSameLevel(Part part)
        //{
        //    if (!this._container.Children.Contains(part))
        //    {
        //        this._container.Children.Add(part);
        //    }
        //    _enteringPart = part;
        //    SwitchAnimationMode = PartFrameSwitchAnimationMode.FrontToBack;
        //}

        /// <summary>
        /// 关闭当前场景，返回上一个场景
        /// </summary>
        public void Back()
        {
            if (_lastPart != null)
            {
                this.SetPartVisible(_lastPart, true);
                if (_leaveingPart != null)
                {
                    Panel.SetZIndex(_leaveingPart, 0);
                }
            }

            if (_currentPart != null)
            {
                _leaveingPart = _currentPart;
                this.SetPartVisible(_leaveingPart, true);
                Panel.SetZIndex(_leaveingPart, 1);

                Common.Logger.WarningToTag("UI", "PartFrame animation Finish enteringPart:{0} type:{1}, 关闭当前场景，返回上一个场景", _switchAnimation.Part.Name, _switchAnimation.Part.GetType().Name);

                _switchAnimation.Prepare(SwitchType.Out, this, _leaveingPart);
                _switchAnimation.Begin();
            }
            _currentPart = _lastPart;
        }

        private PartContext CreatePartContext(Metadata.Scene sceneMetadata)
        {
            // 加载场景的脚本文件
            PartContext.ScriptEngine.Reset();
            // 添加窗口对象，用于交互
            PartContext.ScriptEngine.AddObject("window", this.GetScriptObj());

            if (sceneMetadata != null && sceneMetadata.Scripts != null)
            {
                for (int index = 0; index < sceneMetadata.Scripts.Count; index++)
                {
                    if (!string.IsNullOrEmpty(sceneMetadata.Scripts[index].Source))
                    {
                        string scriptFilePath = UI.SolutionResourceManager.GetAbsoluteFilePath(sceneMetadata.Scripts[index].Source);
                        PartContext.ScriptEngine.AddFile(scriptFilePath);
                    }
                    else if (!string.IsNullOrEmpty(sceneMetadata.Scripts[index].Content))
                    {
                        PartContext.ScriptEngine.AddCode(sceneMetadata.Scripts[index].Content);
                    }
                }
            }
            return PartContext;
        }

        /// <summary>
        /// 初始化PartFrame，
        /// 主要是要初始化PartFrame里的PartContext
        /// </summary>
        /// <param name="solutionMetadata"></param>
        public void Init(Metadata.Solution solutionMetadata)
        {
            PartContext = new PartContext(ScriptEngine.Create(Guid.NewGuid().ToString("N")),
                solutionMetadata,
                null);
        }

        public void SetViewState(Coolzon.ViewState.ViewState viewState)
        {
            if (_currentPart != null)
            {
                _currentPart.LoadViewState(viewState);
            }
            else if (_enteringPart != null)
            {
                _enteringPart.LoadViewState(viewState);
            }
        }

        [Obsolete("bug:应该不需要传递参数")]
        public void Active(Metadata.Scene sceneMetadata, bool isShowActiveXPart, OpenSceneArgs args)
        {
            PartContext partContext = CreatePartContext(sceneMetadata);
            partContext.IsShowActiveXPart = isShowActiveXPart;
            partContext.OpenSceneArgs = args;
            partContext.SceneMetadata = sceneMetadata;

            this.Active(partContext);
        }

        protected override void OnActive(PartContext context)
        {
            if (this._leaveingPart != null)
            {
                this._leaveingPart.Destory();
                this._container.Children.Remove(this._leaveingPart);
                this._leaveingPart = null;
            }

            if (this._enteringPart == null)
            {
                this._currentPart = null;
                return;
            }

            this._currentPart = this._enteringPart;
            this._enteringPart = null;
            this._container.Children.Add(this._currentPart);

            if (this._isAutoSize && this._currentPart != null)
            {
                this.Width = this._currentPart.XWidth;
                this.Height = this._currentPart.XHeight;
            }

            // 直接打开
            _currentPart.Active(context);
            MoveCameraToPos(0, 0);

            #region 设置容器的大小，让容器的大小和场景的大次一样

            Common.Logger.DebugToTag("UI", "设置_container大小为:{0},{1},children:{2}", _currentPart.Width, _currentPart.Height,
                _container.Children.Count);
            _container.Width = _currentPart.Width;
            _container.Height = _currentPart.Height;
            #endregion

            if (OnSceneOpened != null)
            {
                OnSceneOpened(_currentPart as ScenePart);
            }

            /*
            if (_currentPart!=null)
            {
            }

            if (_switchAnimation != null)
            {
                Common.Logger.DebugToTag("UI", "PartFrame active 正有场景在切换中,scene:{0}", _switchAnimation.Part.Name);
                this.SetPartVisible(_switchAnimation.Part, false);
                Panel.SetZIndex(_switchAnimation.Part, 0);
                _switchAnimation.Stop();
            }


            if (_enteringAnimation == null)
            {
                return;
            }

            _switchAnimation = _enteringAnimation;
            _enteringAnimation = null;
            Part enteringPart =  _switchAnimation.Part;
            //_leaveingPart = _currentPart;
            //_currentPart = part;

            if (enteringPart != null)
            {
                Common.Logger.DebugToTag("UI", "PartFrame Active 显示场景:{0},开始执行动画", enteringPart.Name);
                //if (this._leaveingPart != null)
                //{
                //    this.SetPartVisible(_leaveingPart, false);
                //}
                //_leaveingPart = _currentPart;
                //if (_leaveingPart != null)
                //{
                //    this.SetPartVisible(_leaveingPart, true);
                //    Panel.SetZIndex(_leaveingPart, 0);
                //}
                if (_leaveingPart != null)
                {
                    Panel.SetZIndex(_leaveingPart, 0);
                }
                this.SetPartVisible(enteringPart, true);
                Panel.SetZIndex(enteringPart, 1);

                _switchType = SwitchType.In;
                _switchAnimation.SwitchFinish += _switchAnimation_SwitchFinish;

                //_lastPart = _currentPart;
                //_currentPart = _enteringPart;

                //_switchAnimation.Prepare(_switchType, this, _enteringPart);
                _switchAnimation.Begin();
            }
            else if (_currentPart != null && _leaveingPart == null)
            {
                // 直接打开
                _currentPart.Active(context);
                MoveCameraToPos(0, 0);
                if (OnSceneOpened != null)
                {
                    OnSceneOpened(_currentPart as ScenePart);
                }
            }
             * */
        }

        void _switchAnimation_SwitchFinish(SwitchAnimation animation, SwitchAnimationArgs args)
        {
            if (animation.State != SwitchAnimationState.Finished)
            {
                Common.Logger.DebugToTag("UI", "销毁-位置1,animation.Part，Name:{0}", animation.Part.Name);
                //this.SetPartVisible(animation.Part, false);
                //// 销毁动画的场景
                //animation.Part.Destory();
                return;
            }

            Common.Logger.DebugToTag("UI", "PartFrame animation Finish enteringPart:{0} type:{1}", animation.Part.Name, animation.Part.GetType().Name);

            if (animation != _switchAnimation)
            {
                if (_switchAnimation == null)
                {
                    Common.Logger.WarningToTag("UI", "PartFrame animation Finish enteringPart:{0} type:{1}, _switchAnimation为null， end animation error not same animation", animation.Part.Name, animation.Part.GetType().Name);
                }
                else
                {
                    Part enteringPart = _switchAnimation.Part;
                    Common.Logger.WarningToTag("UI", "PartFrame animation Finish enteringPart:{0} type:{1},currentAnimation:{2}, type:{3}, end animation error not same animation", enteringPart.Name, enteringPart.GetType().Name, animation.Part.Name, animation.Part.GetType().Name);
                }
                //Common.Logger.DebugToTag("UI", "销毁-位置2,animation.Part，Name:{0}", animation.Part.Name);
                //this.SetPartVisible(animation.Part, false);
                //// 销毁动画的场景
                //animation.Part.Destory();

                //// 销毁退出的场景
                //if (this._leaveingPart != null)
                //{
                //    Common.Logger.DebugToTag("UI", "销毁-位置1,leaveingPart，Name:{0}", _leaveingPart.Name);
                //    this.SetPartVisible(_leaveingPart, false);
                //    // 销毁当前场景
                //    this._leaveingPart.Destory();
                //    this._leaveingPart = null;
                //}
            }
            else
            {
                // 销毁退出的场景
                if (this._leaveingPart != null)
                {
                    Common.Logger.DebugToTag("UI", "销毁-位置2,leaveingPart，Name:{0}", _leaveingPart.Name);
                    this.SetPartVisible(_leaveingPart, false);
                    // 销毁当前场景
                    this._leaveingPart.Destory();
                    this._leaveingPart = null;
                }
                _enteringPart = null;

                this.SetPartVisible(_currentPart, true);
                _currentPart.Active(PartContext);
                MoveCameraToPos(0, 0);

                // 动画结束
                _switchAnimation = null;

                Common.Logger.DebugToTag("UI", "PartFrame animation _switchAnimation赋值为null-动画结束");

                #region 调整组件的可视区域，解决activex组件在刚加载完毕时显示有问题的bug
                //if (_currentPart != null)
                //{
                //    Point ltInContainer = _scrollViewer.PointToScreen(new Point(0, 0));
                //    Point rtInContainer = _scrollViewer.PointToScreen(new Point(_scrollViewer.ActualWidth, _scrollViewer.ActualHeight));
                //    _currentPart.VisibleRegionChange(ltInContainer, rtInContainer);
                //}
                #endregion
                ScenePart scenePart = (_currentPart as ScenePart);
                if (_hLoopOffset > 0)
                {

                    Common.Logger.DebugToTag("UI", "exist hLoopOffset, scene:{0} HLoop offset:{1}", scenePart.XFullName, _hLoopOffset);
                    scenePart.HorizontalLoop(_hLoopOffset);
                    _hLoopOffset = 0;
                }

                #region 设置容器的大小，让容器的大小和场景的大次一样

                Common.Logger.DebugToTag("UI", "设置_container大小为:{0},{1}", _currentPart.Width, _currentPart.Height);
                _container.Width = _currentPart.Width;
                _container.Height = _currentPart.Height;
                #endregion

                UpdateDisplayMode();

                if (OnSceneOpened != null)
                {
                    OnSceneOpened(_currentPart as ScenePart);
                    Common.Logger.DebugToTag("UI", "OnSceneOpened 执行完毕");
                }
            }
        }

        private double GetLayoutScaleX()
        {
            if (DisplayMode == PartFrameDisplayMode.Stretch)
            {
                if (this._currentPart != null && _currentPart.ActualWidth > 0 && _currentPart.ActualHeight > 0)
                {
                    return this.ActualWidth / this._currentPart.ActualWidth;
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.HStretch)
            {
                if (this._currentPart != null && _currentPart.ActualWidth > 0 && _currentPart.ActualHeight > 0)
                {
                    return this.ActualWidth / this._currentPart.ActualWidth;
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.VStretch)
            {
                if (this._currentPart != null && _currentPart.ActualWidth > 0 && _currentPart.ActualHeight > 0)
                {
                    return this.ActualHeight / this._currentPart.ActualHeight;
                }
            }
            return 1;
        }

        private double GetLayoutScaleY()
        {
            if (DisplayMode == PartFrameDisplayMode.Stretch)
            {
                if (this._currentPart != null && _currentPart.ActualWidth > 0 && _currentPart.ActualHeight > 0)
                {
                    return this.ActualHeight / this._currentPart.ActualHeight;
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.HStretch)
            {
                if (this._currentPart != null && _currentPart.ActualWidth > 0 && _currentPart.ActualHeight > 0)
                {
                    return this.ActualWidth / this._currentPart.ActualWidth;
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.VStretch)
            {
                if (this._currentPart != null && _currentPart.ActualWidth > 0 && _currentPart.ActualHeight > 0)
                {
                    return this.ActualHeight / this._currentPart.ActualHeight;
                }
            }
            return 1;
        }

        public void UpdateDisplayMode()
        {
            return;

            if (this.Content == null)
            {
                return;
            }

            MoveOutFromScrollView();

            if (DisplayMode == PartFrameDisplayMode.Stretch)
            {
                FrameworkElement contentElement = this.Content as FrameworkElement;
                if (this._currentPart != null && contentElement.ActualWidth > 0 && contentElement.ActualHeight > 0)
                {
                    ScaleTransform scaleTransform = new ScaleTransform();
                    scaleTransform.CenterX = 0.5f;
                    scaleTransform.CenterY = 0.5f;
                    scaleTransform.ScaleX = this.ActualWidth / this._currentPart.ActualWidth;
                    scaleTransform.ScaleY = this.ActualHeight / this._currentPart.ActualHeight;
                    this._container.LayoutTransform = scaleTransform;
                    // 移动滚动视图内
                    MoveInToScrollView();
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.HStretch)
            {
                FrameworkElement contentElement = this.Content as FrameworkElement;
                if (this._currentPart != null && contentElement.ActualWidth > 0 && contentElement.ActualHeight > 0)
                {
                    ScaleTransform scaleTransform = new ScaleTransform();
                    scaleTransform.CenterX = 0.5f;
                    scaleTransform.CenterY = 0.5f;
                    scaleTransform.ScaleX = this.ActualWidth / this._currentPart.ActualWidth;
                    scaleTransform.ScaleY = scaleTransform.ScaleX;
                    this._container.LayoutTransform = scaleTransform;
                    // 移动滚动视图内
                    MoveInToScrollView();
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.VStretch)
            {
                FrameworkElement contentElement = this.Content as FrameworkElement;
                if (this._currentPart != null && contentElement.ActualWidth > 0 && contentElement.ActualHeight > 0)
                {
                    ScaleTransform scaleTransform = new ScaleTransform();
                    scaleTransform.CenterX = 0.5f;
                    scaleTransform.CenterY = 0.5f;
                    scaleTransform.ScaleX = this.ActualHeight / this._currentPart.ActualHeight;
                    scaleTransform.ScaleY = this.ActualHeight / this._currentPart.ActualHeight;
                    this._container.LayoutTransform = scaleTransform;

                    // 移动滚动视图内
                    MoveInToScrollView();
                }
            }
            else if (DisplayMode == PartFrameDisplayMode.Original)
            {
                //FrameworkElement contentElement = this.Content as FrameworkElement;
                //if (this._currentPart != null && contentElement.ActualWidth > 0 && contentElement.ActualHeight > 0)
                //{
                //    ScaleTransform scaleTransform = new ScaleTransform();
                //    scaleTransform.ScaleX = 1;
                //    scaleTransform.ScaleY = 1;
                //    this._container.LayoutTransform = scaleTransform;

                //    // 移动滚动视图内
                //    MoveInToScrollView();
                //}
            }

            if (this._currentPart != null)
            {
                FrameSize = new Size(this.ActualWidth, this.ActualHeight);
                ContentSize = new Size(this._currentPart.RenderSize.Width, this._currentPart.RenderSize.Height);
            }

            if (!_hasUpdateDisplayMode)
            {
                _hasUpdateDisplayMode = true;
            }
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            // 大小改变的时候，调整显示组件的缩放大小
            if (_hasUpdateDisplayMode)
            {
                UpdateDisplayMode();
            }

            if (this.Content == _scrollViewer)
            {
                ValidateCurrentPartVisibleRange();
            }

            base.OnRenderSizeChanged(sizeInfo);
        }

        /// <summary>
        /// 从滚动试图中移出
        /// </summary>
        private void MoveOutFromScrollView()
        {
            return;

            if (!IsCanScroll)
            {
                return;
            }
            if (_currentPart == null)
            {
                return;
            }
            if (this.Content != _container)
            {
                /*
                this.Content = null;
                this._scrollViewer.Content = null;
                this.Content = _container;
                */

                /*
                _scrollViewer.Content = null;
                _currentPart.LayoutTransform = null;
                this.Content = _container;
                if (!_container.Children.Contains(_currentPart))
                {
                    _container.Children.Add(_currentPart);
                }
                this._scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
                this._scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
                 * */
            }
        }

        /// <summary>
        /// 移入到滚动试图
        /// </summary>
        private void MoveInToScrollView()
        {
            return;

            if (!IsCanScroll)
            {
                return;
            }
            if (_currentPart == null)
            {
                return;
            }
            if (this.Content != _scrollViewer)
            {
                /*
                this.Content = _scrollViewer;
                this._scrollViewer.Content = _container;
                this._scrollViewer.ScrollToTop();
                 * */
            }
        }

        public void Clear()
        {
            this.Content = null;
            this._container.Children.Clear();
            //this._scrollViewer.Content = null;
            this._scrollViewer.Children.Clear();
        }

        #region dependency method

        private static void OnHorizontalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PartFrame frame = d as PartFrame;
            //frame._scrollViewer.ScrollToHorizontalOffset((double)e.NewValue);
            for (int index = 0; index < frame._scrollViewer.Children.Count; index++)
            {
                Canvas.SetLeft(frame._scrollViewer.Children[index], -(double)e.NewValue);
            }
        }

        private static void OnVerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PartFrame frame = d as PartFrame;
            //frame._scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
            for (int index = 0; index < frame._scrollViewer.Children.Count; index++)
            {
                Canvas.SetTop(frame._scrollViewer.Children[index], -(double)e.NewValue);
            }
        }

        #endregion

        //public void Active()
        //{
        //    OnActive();
        //}

        protected override void OnDeactive(PartContext context)
        {
            if (this.Layout != null)
            {
                for (int index = 0; index < this.Layout.Frames.Count; index++)
                {
                    this.Layout.Frames[index].Deactive();
                }
            }

            if (_currentPart != null)
            {
                _currentPart.Deactive();
            }

            base.OnDeactive(context);
        }

        public void SetLayout(Layout layout)
        {
            this.Content = layout.GetUIContent();
        }

        //protected override void OnMouseWheel(System.Windows.Input.MouseWheelEventArgs e)
        //{
        //    if (this.IsCanScroll && this.RenderSize.Height < this._currentPart.RenderSize.Height)
        //    {
        //        //this.HorizontalOffset += e.Delta;
        //        //this._currentPart.Margin = new Thickness(0, e.Delta, 0, -1 * e.Delta);
        //        this._currentPart.Margin = new Thickness(0, -100, 0, 100);
        //    }
        //    base.OnMouseWheel(e);
        //}

        public void HLoopTo(double destOffset)
        {
            ScenePart scenePart = _currentPart as ScenePart;
            if (_currentPart != null)
            {
                double offset = destOffset - scenePart.CurrentHLoopOffset;
                _hLoopOffset = offset;
                Common.Logger.DebugToTag("UI", "scene:{0} HLoop offset:{1}", scenePart.XFullName, offset);
                scenePart.HorizontalLoop(_hLoopOffset);
                _hLoopOffset = 0;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="offset">本次增量</param>
        public void HLoop(double offset)
        {
            _hLoopOffset = offset;
            ScenePart scenePart = _currentPart as ScenePart;
            if (_currentPart != null)
            {
                Common.Logger.DebugToTag("UI", "scene:{0} HLoop offset:{1}", scenePart.XFullName, offset);
                scenePart.HorizontalLoop(_hLoopOffset);
                _hLoopOffset = 0;
            }
            else
            {
                Common.Logger.WarningToTag("UI", "PartFrame HLoop offset:{0}, scene is null, save offset", offset);
            }
        }

        public void ExecuteJs(string scriptCode)
        {
            PartContext.ScriptEngine.RunExpression(scriptCode);
        }

        /// <summary>
        /// 清楚渲染视图里所有的组件引用关系
        /// </summary>
        public void ClearAllParts()
        {
            if (_moveAreaStoryboard != null)
            {
                _moveAreaStoryboard.Stop();
                _moveAreaStoryboard.Remove();
                _moveAreaStoryboard = null;
            }

            for (int index = 0; index < _container.Children.Count; index++)
            {
                UI.Part part = _container.Children[index] as UI.Part;
                part.Destory();
            }
            _container.Children.Clear();

            if (PartContext != null)
            {
                PartContext.Clear();
            }

            if (_switchAnimation != null)
                Common.Logger.DebugToTag("UI", "PartFrame animation _switchAnimation赋值为null-ClearAllParts,Part:{0},type:{1}", _switchAnimation.Part.XFullName, _switchAnimation.Part.GetType().Name);
            else
            {
                Common.Logger.DebugToTag("UI", "PartFrame animation _switchAnimation赋值为null-ClearAllParts");
            }

            _currentPart = null;
            _enteringPart = null;
            _leaveingPart = null;
            _switchAnimation = null;
            _enteringAnimation = null;

        }

        #region 放大镜

        /// <summary>
        /// 显示放大镜
        /// </summary>
        /// <param name="pos">放大的位置</param>
        /// <param name="rate">倍率</param>
        /// <param name="radius">放大的半径</param>
        /// <param name="duration">移动持续时间</param>
        public void ShowMagnify(Point pos, double rate, double radius, double duration)
        {
            double offsetX = 800 / 2;
            double offsetY = 800 / 2;
            if (XMagnifySource == null)
            {
                VisualBrush brush = new VisualBrush();
                brush.ViewboxUnits = BrushMappingMode.Absolute;
                brush.Viewbox = new Rect(0, 0, 800 / this._magnifyRate, 800 / this._magnifyRate);
                brush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox;
                brush.Viewport = new Rect(new Point(0, 0), new Vector(1, 1));
                brush.Visual = this.CurrentPart;
                brush.AlignmentX = AlignmentX.Left;
                brush.AlignmentY = AlignmentY.Top;
                //brush.Stretch = Stretch.None;

                XMagnifySource = brush;
            }

            //Rect viewBox = (XMagnifySource as VisualBrush).Viewbox;
            //double xoffset = viewBox.Width / 2.0;
            //double yoffset = viewBox.Height / 2.0;
            //viewBox.X = pos.X - xoffset;
            //viewBox.Y = pos.Y - yoffset;
            //(XMagnifySource as VisualBrush).Viewbox = viewBox;

            if (_moveMagnifyStoryboard == null)
            {
                _moveMagnifyStoryboard = new Storyboard();
                //_moveMagnifyStoryboard.FillBehavior = FillBehavior.HoldEnd;
                _moveMagnifyAnimationTop = new DoubleAnimation(this.XLaserPointerTop, pos.Y - offsetY, new Duration(TimeSpan.FromSeconds(duration)));
                Storyboard.SetTarget(_moveMagnifyAnimationTop, this);
                Storyboard.SetTargetProperty(_moveMagnifyAnimationTop, new PropertyPath(PartFrame.XMagnifyTopProperty));

                _moveMagnifyAnimationLeft = new DoubleAnimation(this.XLaserPointerLeft, pos.X - offsetX, new Duration(TimeSpan.FromSeconds(duration)));
                Storyboard.SetTarget(_moveMagnifyAnimationLeft, this);
                Storyboard.SetTargetProperty(_moveMagnifyAnimationLeft, new PropertyPath(PartFrame.XMagnifyLeftProperty));

                _moveMagnifyStoryboard.Children.Add(_moveMagnifyAnimationTop);
                _moveMagnifyStoryboard.Children.Add(_moveMagnifyAnimationLeft);
                _moveMagnifyStoryboard.Begin(this);
            }
            else
            {
                _moveMagnifyAnimationTop.From = this.XMagnifyTop;
                _moveMagnifyAnimationTop.To = pos.Y - offsetY;

                _moveMagnifyAnimationLeft.From = this.XMagnifyLeft;
                _moveMagnifyAnimationLeft.To = pos.X - offsetX;
                //_moveMagnifyStoryboard.Remove(this);
                _moveMagnifyStoryboard.Begin(this);
            }
            XIsShowMagnify = true;
        }

        /// <summary>
        /// 隐藏放大镜
        /// </summary>
        public void HideMagnify()
        {
            XMagnifySource = null;
            XIsShowMagnify = false;
        }

        #region laser pointer
        public void ShowLaserPointer(Point pos, double radius, double duration, int color)
        {
            double halfW = 90 / 2;
            double halfH = 90 / 2;
            if (_moveLaserPointerStoryboard == null)
            {
                _moveLaserPointerStoryboard = new Storyboard();

                _moveLaserPointerAnimationTop = new DoubleAnimation(this.XLaserPointerTop, pos.Y - halfH, new Duration(TimeSpan.FromSeconds(duration)));
                Storyboard.SetTarget(_moveLaserPointerAnimationTop, this);
                Storyboard.SetTargetProperty(_moveLaserPointerAnimationTop, new PropertyPath(PartFrame.XLaserPointerTopProperty));

                _moveLaserPointerAnimationLeft = new DoubleAnimation(this.XLaserPointerLeft, pos.X - halfW, new Duration(TimeSpan.FromSeconds(duration)));
                Storyboard.SetTarget(_moveLaserPointerAnimationLeft, this);
                Storyboard.SetTargetProperty(_moveLaserPointerAnimationLeft, new PropertyPath(PartFrame.XLaserPointerLeftProperty));

                _moveLaserPointerStoryboard.Children.Add(_moveLaserPointerAnimationTop);
                _moveLaserPointerStoryboard.Children.Add(_moveLaserPointerAnimationLeft);
                _moveLaserPointerStoryboard.Begin(this);
            }
            else
            {
                _moveLaserPointerAnimationTop.From = this.XLaserPointerTop;
                _moveLaserPointerAnimationTop.To = pos.Y - halfH;

                _moveLaserPointerAnimationLeft.From = this.XLaserPointerLeft;
                _moveLaserPointerAnimationLeft.To = pos.X - halfW;
                _moveLaserPointerStoryboard.Begin(this);
            }
            //XLaserPointerLeft = pos.X - 50;
            //XLaserPointerTop = pos.Y - 50;
            XLaserPointerColor = new SolidColorBrush(Color.FromRgb(0x8F, 0xFF, 0x00));
            XIsShowLaserPointer = true;
        }

        public void HideLaserPointer()
        {
            XIsShowLaserPointer = false;
        }
        #endregion

        //protected override void OnPreviewMouseDown(System.Windows.Input.MouseButtonEventArgs e)
        //{
        //    Point pt = e.GetPosition(this.CurrentPart);
        //    //ShowMagnify(pt, 1, 10, 10);
        //    ShowLaserPointer(pt, 1, 1, 1);
        //    base.OnPreviewMouseDown(e);
        //}

        //protected override void OnPreviewMouseMove(System.Windows.Input.MouseEventArgs e)
        //{
        //    if (XIsShowMagnify)
        //    {
        //        Point pt = e.GetPosition(this.CurrentPart);
        //        ShowMagnify(pt, 1, 10, 10);

        //    }
        //    else if (XIsShowLaserPointer)
        //    {
        //        Point pt = e.GetPosition(this.CurrentPart);
        //        ShowLaserPointer(pt, 1, 1, 1);

        //    }
        //    base.OnPreviewMouseMove(e);
        //}

        //protected override void OnPreviewMouseUp(System.Windows.Input.MouseButtonEventArgs e)
        //{
        //    //HideMagnify();
        //    HideLaserPointer();
        //    base.OnPreviewMouseUp(e);
        //}

        #endregion

        public void SwapArea(string sourceArea, string destArea)
        {
            Storyboard storyboard = new Storyboard();
            storyboard.FillBehavior = FillBehavior.HoldEnd;

            IPartContainer partContainer = this.CurrentPart as IPartContainer;

            AreaPart objSourceArea = partContainer.GetChildPart(sourceArea, true) as AreaPart;
            AreaPart objDestArea = partContainer.GetChildPart(destArea, true) as AreaPart;

            double beginLeft = 0;
            double endLeft = 0;
            double delta = 0;
            if (objSourceArea.XLeft < objDestArea.XLeft)
            {
                beginLeft = objSourceArea.XLeft;
                endLeft = objDestArea.XLeft;
                delta = objDestArea.XWidth - objSourceArea.XWidth;
            }
            else
            {
                beginLeft = objDestArea.XLeft;
                endLeft = objSourceArea.XLeft;
                delta = objSourceArea.XWidth - objDestArea.XWidth;
            }

            for (int index = 0; index < partContainer.GetPartList().Count; index++)
            {
                Part part = partContainer.GetPartList()[index];
                if (part.XLeft > beginLeft
                    && part.XLeft < endLeft)
                {
                    //partContainer.PartList[index].XLeft += delta;

                    DoubleAnimationUsingKeyFrames daukf = new DoubleAnimationUsingKeyFrames();
                    daukf.KeyFrames.Add(new EasingDoubleKeyFrame(part.XLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
                    daukf.KeyFrames.Add(new EasingDoubleKeyFrame(part.XLeft + delta, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2))));
                    Storyboard.SetTarget(daukf, part);
                    Storyboard.SetTargetProperty(daukf, new PropertyPath(Part.XLeftProperty));
                    storyboard.Children.Add(daukf);
                }
            }

            double destOffset = 0;
            double sourceOffset = 0;
            if (objSourceArea.XLeft < objDestArea.XLeft)
            {
                destOffset = beginLeft;
                sourceOffset = endLeft + delta;
            }
            else
            {
                sourceOffset = beginLeft;
                destOffset = endLeft + delta;
            }

            // dest area 消失
            DoubleAnimationUsingKeyFrames opcityDestAnimation1 = new DoubleAnimationUsingKeyFrames();
            opcityDestAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            opcityDestAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
            Storyboard.SetTarget(opcityDestAnimation1, objDestArea);
            Storyboard.SetTargetProperty(opcityDestAnimation1, new PropertyPath(UIElement.OpacityProperty));
            storyboard.Children.Add(opcityDestAnimation1);

            // dest area 移动
            DoubleAnimationUsingKeyFrames moveDestAnimation1 = new DoubleAnimationUsingKeyFrames();
            moveDestAnimation1.KeyFrames.Add(new DiscreteDoubleKeyFrame(objDestArea.XLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
            moveDestAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(destOffset, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2))));
            Storyboard.SetTarget(moveDestAnimation1, objDestArea);
            Storyboard.SetTargetProperty(moveDestAnimation1, new PropertyPath(Part.XLeftProperty));
            storyboard.Children.Add(moveDestAnimation1);

            // dest area 出现
            DoubleAnimationUsingKeyFrames opcityDestAnimation2 = new DoubleAnimationUsingKeyFrames();
            opcityDestAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2))));
            opcityDestAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))));
            Storyboard.SetTarget(opcityDestAnimation2, objDestArea);
            Storyboard.SetTargetProperty(opcityDestAnimation2, new PropertyPath(UIElement.OpacityProperty));
            storyboard.Children.Add(opcityDestAnimation2);

            // source area 消失
            DoubleAnimationUsingKeyFrames opcityAnimation1 = new DoubleAnimationUsingKeyFrames();
            opcityAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            opcityAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
            Storyboard.SetTarget(opcityAnimation1, objSourceArea);
            Storyboard.SetTargetProperty(opcityAnimation1, new PropertyPath(UIElement.OpacityProperty));
            storyboard.Children.Add(opcityAnimation1);

            // source area 移动
            DoubleAnimationUsingKeyFrames moveAnimation1 = new DoubleAnimationUsingKeyFrames();
            moveAnimation1.KeyFrames.Add(new DiscreteDoubleKeyFrame(objSourceArea.XLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
            moveAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(sourceOffset, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2))));
            Storyboard.SetTarget(moveAnimation1, objSourceArea);
            Storyboard.SetTargetProperty(moveAnimation1, new PropertyPath(Part.XLeftProperty));
            storyboard.Children.Add(moveAnimation1);

            // source area 出现
            DoubleAnimationUsingKeyFrames opcityAnimation2 = new DoubleAnimationUsingKeyFrames();
            opcityAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2))));
            opcityAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))));
            Storyboard.SetTarget(opcityAnimation2, objSourceArea);
            Storyboard.SetTargetProperty(opcityAnimation2, new PropertyPath(UIElement.OpacityProperty));
            storyboard.Children.Add(opcityAnimation2);

            storyboard.Begin();
        }

        public void MoveArea(string sourceArea, string destArea)
        {
            if (_moveAreaStoryboard != null)
            {
                _moveAreaStoryboard.Stop();
                _moveAreaStoryboard.Remove();
                _moveAreaStoryboard = null;
            }

            _moveSourceArea = sourceArea;
            _moveDestArea = destArea;

            _moveAreaStoryboard = new Storyboard();
            _moveAreaStoryboard.FillBehavior = FillBehavior.Stop;
            _moveAreaStoryboard.Completed += _moveAreaStoryboard_Completed;

            IPartContainer partContainer = this.CurrentPart as IPartContainer;
            ScenePart scenePart = this.CurrentPart as UI.ScenePart;

            AreaPart objSourceArea = partContainer.GetChildPart(sourceArea, true) as AreaPart;
            AreaPart objDestArea = partContainer.GetChildPart(destArea, true) as AreaPart;

            double sourceNewLeft = 0;
            double beginLeft = 0;
            double endLeft = 0;
            double delta = 0;

            if (objSourceArea.XLeft < objDestArea.XLeft)
            {
                // 从左往右插入
                beginLeft = objSourceArea.XLeft;
                endLeft = objDestArea.XLeft;
                delta = -objSourceArea.XWidth;
                sourceNewLeft = -objSourceArea.XWidth + objDestArea.XLeft + objDestArea.XWidth;

                for (int index = 0; index < partContainer.GetPartList().Count; index++)
                {
                    Part part = partContainer.GetPartList()[index];
                    if (part.XLeft > beginLeft
                        && part.XLeft <= endLeft)
                    {
                        DoubleAnimationUsingKeyFrames daukf = new DoubleAnimationUsingKeyFrames();
                        daukf.KeyFrames.Add(new EasingDoubleKeyFrame(part.XLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.2d))));
                        daukf.KeyFrames.Add(new EasingDoubleKeyFrame(part.XLeft + delta, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)), new PowerEase()));
                        Storyboard.SetTarget(daukf, part);
                        Storyboard.SetTargetProperty(daukf, new PropertyPath(Part.XLeftProperty));
                        _moveAreaStoryboard.Children.Add(daukf);
                        // 更新区域的位置
                        scenePart.ChildrenPosInfo.Set(part.Name, part.XLeft + delta);
                    }
                }
            }
            else
            {
                // 从右往左插入
                beginLeft = objSourceArea.XLeft;
                endLeft = objDestArea.XLeft;
                delta = objSourceArea.XWidth;
                sourceNewLeft = objDestArea.XLeft;

                for (int index = 0; index < partContainer.GetPartList().Count; index++)
                {
                    Part part = partContainer.GetPartList()[index];
                    if (part.XLeft < beginLeft
                        && part.XLeft >= endLeft)
                    {
                        DoubleAnimationUsingKeyFrames daukf = new DoubleAnimationUsingKeyFrames();
                        daukf.KeyFrames.Add(new EasingDoubleKeyFrame(part.XLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.2d))));
                        daukf.KeyFrames.Add(new EasingDoubleKeyFrame(part.XLeft + delta, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)), new PowerEase()));
                        Storyboard.SetTarget(daukf, part);
                        Storyboard.SetTargetProperty(daukf, new PropertyPath(Part.XLeftProperty));
                        _moveAreaStoryboard.Children.Add(daukf);
                        // 更新区域的位置
                        scenePart.ChildrenPosInfo.Set(part.Name, part.XLeft + delta);
                    }
                }
            }
            // source area 消失
            DoubleAnimationUsingKeyFrames opcityAnimation1 = new DoubleAnimationUsingKeyFrames();
            opcityAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            opcityAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.2d))));
            Storyboard.SetTarget(opcityAnimation1, objSourceArea);
            Storyboard.SetTargetProperty(opcityAnimation1, new PropertyPath(UIElement.OpacityProperty));
            _moveAreaStoryboard.Children.Add(opcityAnimation1);

            // source area 移动
            DoubleAnimationUsingKeyFrames moveAnimation1 = new DoubleAnimationUsingKeyFrames();
            //moveAnimation1.KeyFrames.Add(new DiscreteDoubleKeyFrame(objSourceArea.XLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5d))));
            moveAnimation1.KeyFrames.Add(new DiscreteDoubleKeyFrame(sourceNewLeft, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.2d))));
            Storyboard.SetTarget(moveAnimation1, objSourceArea);
            Storyboard.SetTargetProperty(moveAnimation1, new PropertyPath(Part.XLeftProperty));
            _moveAreaStoryboard.Children.Add(moveAnimation1);
            // 更新区域的位置
            scenePart.ChildrenPosInfo.Set(objSourceArea.Name, sourceNewLeft);

            // source area 出现
            DoubleAnimationUsingKeyFrames opcityAnimation2 = new DoubleAnimationUsingKeyFrames();
            opcityAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1))));
            opcityAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.2d))));
            Storyboard.SetTarget(opcityAnimation2, objSourceArea);
            Storyboard.SetTargetProperty(opcityAnimation2, new PropertyPath(UIElement.OpacityProperty));
            _moveAreaStoryboard.Children.Add(opcityAnimation2);

            _moveAreaStoryboard.Begin();
        }

        void _moveAreaStoryboard_Completed(object sender, EventArgs e)
        {
            ClockGroup clockGroup = sender as ClockGroup;
            if (clockGroup.CurrentState == ClockState.Stopped)
            {
                ScenePart scenePart = this.CurrentPart as UI.ScenePart;
                for (int index = 0; index < scenePart.SceneMatadata.Areas.Count; index++)
                {
                    Coolzon.Metadata.Area areaMetadata = scenePart.SceneMatadata.Areas[index];
                    UI.AreaPart area = scenePart.GetChildPart(areaMetadata.Name, false) as UI.AreaPart;
                    if (area != null)
                    {
                        area.XLeft = scenePart.ChildrenPosInfo.Get(areaMetadata.Name).Left;
                    }
                }

                Common.EventBus.Instance.Publish(new Event.SwapAreaCompletedEvent(scenePart.SceneMatadata.Name, _moveSourceArea, _moveDestArea));
            }
        }

        #region view state
        public void LoadViewState(Coolzon.ViewState.ViewState viewState)
        {
            ScenePart scene = this.CurrentPart as ScenePart;
            if (scene != null)
            {
                scene.LoadViewState(viewState);
            }
        }

        public void SaveViewState(Coolzon.ViewState.ViewState viewState)
        {
            ScenePart scene = this.CurrentPart as ScenePart;
            if (scene != null)
            {
                scene.SaveViewState(viewState);
            }
        }
        #endregion

        /// <summary>
        /// 获取显示的场景的大小
        /// </summary>
        /// <returns></returns>
        public Size GetSceneSize()
        {
            if (this._currentPart != null)
            {
                return new Size(_currentPart.XWidth, _currentPart.XHeight);
            }
            return new Size(0, 0);
        }
    }
}
